namespace Game {
    using System;
    using System.Collections;
    using System.Collections.Generic;

    using UnityEngine;
    using UnityEngine.EventSystems;
    using UnityEngine.SceneManagement;

    public class MapInfo {
        public int Id;
        public string Type;
        public string Scene;
        public string Prefab;
    }

    public class Map : MonoBehaviour {
        public static  Map Now = null;

        public static IEnumerator OnInit() {
            allMaps = CsvFile.Load<int, MapInfo>("Map/Map.txt", "Id", 1);
            yield return null;

            onLoading   = Lua.GetInPath<Action<MapInfo>>("Map.OnLoading");
            onLoaded    = Lua.GetInPath<Action<MapInfo>>("Map.OnLoaded");
            onLeave     = Lua.GetInPath<Action<MapInfo>>("Map.OnLeave");

#if UNITY_EDITOR
            string name = SceneManager.GetActiveScene().name;
            foreach (var kv in allMaps) if (name == kv.Value.Scene) { Now.Id = kv.Value.Id; break; }
#else
            Now.Id = 0;
#endif
        }

        public static void Load(int id, Action onFinished = null) {
            var map = Find(id); if (map == null) return;

            if (onLeave != null) onLeave(Find(Now.Id));

            // load a empty level
            SceneManager.LoadScene("Loading");

            if (onLoading != null) onLoading(map);

            MapLoader.Load(map, onFinished);
        }

        public static MapInfo Find(int id) {
            MapInfo ret = null; allMaps.TryGetValue(id, out ret); return ret;
        }

        public static Dictionary<int, MapInfo> allMaps;

        private static Action<MapInfo> onLoading = null;
        private static Action<MapInfo> onLoaded = null;
        private static Action<MapInfo> onLeave = null;

        public int Id { get; set; }

        private void Awake() {
            Now = this;
            StartCoroutine(Application.OnInit());
        }

        public IEnumerator OnLoaded() {
            // EventSystem切换场景需要销毁
            // 因为其引用界面元素，会导致界面元素不能释放
            var es = FindObjectOfType<EventSystem>();
            if (es == null) {
                var proxy = new GameObject("EventSystem");
                es = proxy.AddComponent<EventSystem>();
                proxy.AddComponent<StandaloneInputModule>();
            }
            yield return null;

            var info = Find(Id);
            if (onLoaded != null) onLoaded(info);

            if (info != null && !string.IsNullOrEmpty(info.Prefab)) {
                yield return Assets.InstantiateAsync<GameObject>(info.Prefab);
            }
        }
    }
}
